#include "./Bsp/spi/bsp_spi.h"
#include "stm32f4xx_spi.h"

const double Fsysclk = 800000000.;
Devicepara *pDevicepara;
/* 定义接收缓冲和发送缓冲 */
uint8_t SPI_RX_BUFFER[RX_LEN];
uint8_t SPI_TX_BUFFER[TX_LEN];
/* SPI DR寄存器的地址，可通过查看SPI1一步一步得到 */
#define SPI2_DR_ADDR (uint32_t)0x4000380C
/* 如果定义为DMA传输方式，进行DMA初始化 */
#ifdef USE_DMA_TRANS

static void spi_dma_init(void)
{
    DMA_InitTypeDef DMA_InitStructure;

    /* 打开DMA1时钟 */
    RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_DMA1, ENABLE);

    /* DMA RX config */
    DMA_InitStructure.DMA_Channel = DMA_Channel_0;                          //选择DMA通道
    DMA_InitStructure.DMA_PeripheralBaseAddr = SPI2_DR_ADDR;                //外设地址
    DMA_InitStructure.DMA_Memory0BaseAddr = (uint32_t)SPI_RX_BUFFER;        //存储器0地址
    DMA_InitStructure.DMA_DIR = DMA_DIR_PeripheralToMemory;                 //外部设备到内存
    DMA_InitStructure.DMA_BufferSize = 32;                                  //传输数据长度
    DMA_InitStructure.DMA_PeripheralInc = DMA_PeripheralInc_Disable;        //外设地址不自增
    DMA_InitStructure.DMA_MemoryInc = DMA_MemoryInc_Enable;                 //内存地址自增
    DMA_InitStructure.DMA_MemoryDataSize = DMA_MemoryDataSize_Byte;         //内存数据为8位
    DMA_InitStructure.DMA_PeripheralDataSize = DMA_PeripheralDataSize_Byte; //外设数据为8位
    DMA_InitStructure.DMA_Mode = DMA_Mode_Normal;                           //不采取循环模式
    DMA_InitStructure.DMA_Priority = DMA_Priority_Medium;                   //优先级为中等
    DMA_InitStructure.DMA_FIFOMode = DMA_FIFOMode_Disable;                  //不采取FIFO模式
    DMA_InitStructure.DMA_FIFOThreshold = DMA_FIFOThreshold_Full;           //不采取FIFO模式，该参数无关紧要
    DMA_InitStructure.DMA_MemoryBurst = DMA_MemoryBurst_Single;             //单次传输
    DMA_InitStructure.DMA_PeripheralBurst = DMA_PeripheralBurst_Single;     //单次传输
    DMA_Init(DMA1_Stream3, &DMA_InitStructure);

    /* DMA TX Config */
    DMA_InitStructure.DMA_Channel = DMA_Channel_0;                          //选择DMA通道
    DMA_InitStructure.DMA_PeripheralBaseAddr = SPI2_DR_ADDR;                //外设地址
    DMA_InitStructure.DMA_Memory0BaseAddr = (uint32_t)SPI_TX_BUFFER;        //存储器0地址
    DMA_InitStructure.DMA_DIR = DMA_DIR_MemoryToPeripheral;                 //内存到外部设备
    DMA_InitStructure.DMA_BufferSize = 32;                                  //传输数据长度
    DMA_InitStructure.DMA_PeripheralInc = DMA_PeripheralInc_Disable;        //外设地址不自增
    DMA_InitStructure.DMA_MemoryInc = DMA_MemoryInc_Enable;                 //内存地址自增
    DMA_InitStructure.DMA_MemoryDataSize = DMA_MemoryDataSize_Byte;         //内存数据为8位
    DMA_InitStructure.DMA_PeripheralDataSize = DMA_PeripheralDataSize_Byte; //外设数据为8位
    DMA_InitStructure.DMA_Mode = DMA_Mode_Normal;                           //不采取循环模式
    DMA_InitStructure.DMA_Priority = DMA_Priority_Medium;                   //优先级为中等
    DMA_InitStructure.DMA_FIFOMode = DMA_FIFOMode_Disable;                  //不采取FIFO模式
    DMA_InitStructure.DMA_FIFOThreshold = DMA_FIFOThreshold_Full;           //不采取FIFO模式，该参数无关紧要
    DMA_InitStructure.DMA_MemoryBurst = DMA_MemoryBurst_Single;             //单次传输
    DMA_InitStructure.DMA_PeripheralBurst = DMA_PeripheralBurst_Single;     //单次传输
    DMA_Init(DMA1_Stream4, &DMA_InitStructure);
}
#endif /* USE_DMA_TRANS */

void Spi_Config(void)
{
    GPIO_InitTypeDef GPIO_InitStructure;
    SPI_InitTypeDef SPI_InitStructure;
    //uint16_t tempreg = 0;
    RCC_APB1PeriphClockCmd(RCC_APB1Periph_SPI2, ENABLE);
    RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOB, ENABLE);

    GPIO_InitStructure.GPIO_Pin = (1U << 14) | (1U << 13) | (1U << 15);
    GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;
    GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_DOWN;
    GPIO_InitStructure.GPIO_Speed = GPIO_High_Speed;
    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF;
    GPIO_Init(GPIOB, &GPIO_InitStructure);
    GPIO_PinAFConfig(GPIOB, 13, GPIO_AF_SPI2);
    GPIO_PinAFConfig(GPIOB, 14, GPIO_AF_SPI2);
    GPIO_PinAFConfig(GPIOB, 15, GPIO_AF_SPI2);

    SPI_DeInit(SPI2);

    // tempreg = SPI2->CR1;
    // tempreg &= 0x3040;
    // tempreg |= (uint16_t)((uint32_t)SPI_Direction_2Lines_FullDuplex | SPI_Mode_Master |
    //                       SPI_DataSize_16b | SPI_CPOL_High |
    //                       SPI_CPHA_2Edge | SPI_NSS_Soft |
    //                       SPI_BaudRatePrescaler_16 | SPI_FirstBit_MSB);
    // SPI2->CR1 = tempreg;
    // SPI2->I2SCFGR &= (uint16_t) ~((uint16_t)SPI_I2SCFGR_I2SMOD);
    // SPI2->CRCPR = 7;
    // SPI2->CR1 |= SPI_CR1_SPE;

    GPIO_InitStructure.GPIO_Pin = (1U << 12); //NSS
    GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;
    GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_NOPULL;
    GPIO_InitStructure.GPIO_Speed = GPIO_High_Speed;
    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_OUT;
    GPIO_Init(GPIOB, &GPIO_InitStructure);

    GPIOB->BSRRL |= (1U << 12);
    /* 配置SPI */
    SPI_InitStructure.SPI_Direction = SPI_Direction_2Lines_FullDuplex; //双线双向全双工
    SPI_InitStructure.SPI_Mode = SPI_Mode_Master;                      //主机模式
    SPI_InitStructure.SPI_DataSize = SPI_DataSize_8b;                  //8位传输
    SPI_InitStructure.SPI_CPOL = SPI_CPOL_High;                        //SCK空闲时为高电平
    SPI_InitStructure.SPI_CPHA = SPI_CPHA_2Edge;                       //在时钟线的第二个跳变沿采样数据
    SPI_InitStructure.SPI_NSS = SPI_NSS_Soft;                          //NSS软件模式
    SPI_InitStructure.SPI_BaudRatePrescaler = SPI_BaudRatePrescaler_2; //预分频为256
    SPI_InitStructure.SPI_FirstBit = SPI_FirstBit_MSB;                 //高位传输
    SPI_InitStructure.SPI_CRCPolynomial = 7;                           //数据校验，大于1即可，提高通信可靠性
    SPI_Init(SPI2, &SPI_InitStructure);
#ifdef USE_DMA_TRANS
    SPI_I2S_DMACmd(SPI2, SPI_I2S_DMAReq_Tx, ENABLE);
    SPI_I2S_DMACmd(SPI2, SPI_I2S_DMAReq_Rx, ENABLE);
    spi_dma_init();
#endif /* USE_DMA_TRANS */
    SPI_Cmd(SPI2, ENABLE);
    /* 清除接收标志位 */
    SPI_I2S_ClearITPendingBit(SPI2, SPI_I2S_IT_RXNE);
}

/**
  *	@breif  The spi trans speed config function.
  * @param  speed_mode:
						SPI_PREC_2      //2分频
						SPI_PREC_4	    //4分频
						SPI_PREC_8	    //8分频
						SPI_PREC_16	    //16分频
						SPI_PREC_32     //32分频
						SPI_PREC_64     //64分频
						SPI_PREC_128    //128分频
						SPI_PREC_256    //256分频
  * @retval None
  */
void set_spi_speed(uint8_t speed_mode)
{
    /* 关闭SPI,清零3-5位 */
    SPI2->CR1 &= 0XFF87;

    switch (speed_mode)
    {
    case SPI_PREC_2:
        SPI2->CR1 |= 0 << 3;
        break;

    case SPI_PREC_4:
        SPI2->CR1 |= 1 << 3;
        break;

    case SPI_PREC_8:
        SPI2->CR1 |= 2 << 3;
        break;

    case SPI_PREC_16:
        SPI2->CR1 |= 3 << 3;
        break;

    case SPI_PREC_32:
        SPI2->CR1 |= 4 << 3;
        break;

    case SPI_PREC_64:
        SPI2->CR1 |= 5 << 3;
        break;

    case SPI_PREC_128:
        SPI2->CR1 |= 6 << 3;
        break;

    case SPI_PREC_256:
        SPI2->CR1 |= 7 << 3;
        break;

    default:
        break;
    }
    /* 打开SPI */
    SPI2->CR1 |= 1 << 6;
}

/* 如果定义为DMA传输 */
#ifdef USE_DMA_TRANS

void spi_trans(uint8_t *rx_buf, //接收buffer指针
               uint8_t *tx_buf, //发送buffer指针
               uint16_t length) //传输数据长度
{
    /* 关闭DMA通道 */
    DMA_Cmd(DMA1_Stream3, DISABLE);
    DMA_Cmd(DMA1_Stream4, DISABLE);

    /* 设置传输字节数 */
    DMA_SetCurrDataCounter(DMA1_Stream3, (uint16_t)length);
    DMA_SetCurrDataCounter(DMA1_Stream4, (uint16_t)length);
    /* 发送接收数据存储地址自增 */
    DMA1_Stream3->CR |= (1 << 10);
    DMA1_Stream4->CR |= (1 << 10);

    /* 设置接收和发送的内存地址 */
    DMA1_Stream3->M0AR = (uint32_t)rx_buf;
    DMA1_Stream4->M0AR = (uint32_t)tx_buf;

    /* 读取一次DR，使其清空 */
    SPI2->DR;

    /* 等待发送区为空 */
    while (SPI_I2S_GetFlagStatus(SPI2, SPI_I2S_FLAG_TXE) == RESET)
        ;

    /* 打开DMA通道 */
    DMA_Cmd(DMA1_Stream3, ENABLE);
    DMA_Cmd(DMA1_Stream4, ENABLE);

    /* 传输完成 */
    while (DMA_GetFlagStatus(DMA1_Stream4, DMA_FLAG_TCIF4) == RESET)
        ;
    while (DMA_GetFlagStatus(DMA1_Stream3, DMA_FLAG_TCIF3) == RESET)
        ;

    /* 关闭DMA通道 */
    DMA_Cmd(DMA1_Stream3, DISABLE);
    DMA_Cmd(DMA1_Stream4, DISABLE);

    /* 清除DMA传输完成标志 */
    DMA_ClearFlag(DMA1_Stream3, DMA_FLAG_TCIF3);
    DMA_ClearFlag(DMA1_Stream4, DMA_FLAG_TCIF4);
}

void spi_trans_read(uint8_t *rx_buf,
                    uint8_t *tx_data,
                    uint16_t length)
{
    /* 关闭DMA通道 */
    DMA_Cmd(DMA1_Stream3, DISABLE);
    DMA_Cmd(DMA1_Stream4, DISABLE);

    /* 设置传输字节数 */
    DMA_SetCurrDataCounter(DMA1_Stream3, (uint16_t)length);
    DMA_SetCurrDataCounter(DMA1_Stream4, (uint16_t)length);

    /* 发送DMA流的发送地址不自增 */
    DMA1_Stream4->CR &= ~(1 << 10);

    /* 设置接收和发送的内存地址 */
    DMA1_Stream3->M0AR = (uint32_t)rx_buf;
    DMA1_Stream4->M0AR = (uint32_t)tx_data;

    /* 读取一次DR，使其清空 */
    SPI2->DR;

    /* 等待发送区为空 */
    while (SPI_I2S_GetFlagStatus(SPI2, SPI_I2S_FLAG_TXE) == RESET)
        ;

    /* 打开DMA通道 */
    DMA_Cmd(DMA1_Stream3, ENABLE);
    DMA_Cmd(DMA1_Stream4, ENABLE);

    /* 传输完成 */
    while (DMA_GetFlagStatus(DMA1_Stream4, DMA_FLAG_TCIF4) == RESET)
        ;
    while (DMA_GetFlagStatus(DMA1_Stream3, DMA_FLAG_TCIF3) == RESET)
        ;

    /* 关闭DMA通道 */
    DMA_Cmd(DMA1_Stream3, DISABLE);
    DMA_Cmd(DMA1_Stream4, DISABLE);

    /* 清除DMA传输完成标志 */
    DMA_ClearFlag(DMA1_Stream3, DMA_FLAG_TCIF3);
    DMA_ClearFlag(DMA1_Stream4, DMA_FLAG_TCIF4);
}

void spi_trans_write(uint8_t *rx_data,
                     uint8_t *tx_buffer,
                     uint16_t length)
{
    /* 关闭DMA通道 */
    DMA_Cmd(DMA1_Stream3, DISABLE);
    DMA_Cmd(DMA1_Stream4, DISABLE);

    /* 设置传输字节数 */
    DMA_SetCurrDataCounter(DMA1_Stream3, (uint16_t)length);
    DMA_SetCurrDataCounter(DMA1_Stream4, (uint16_t)length);

    /* 接收DMA流的接收地址不自增 */
    DMA1_Stream3->CR &= ~(1 << 10);

    /* 设置接收和发送的内存地址 */
    DMA1_Stream3->M0AR = (uint32_t)rx_data;
    DMA1_Stream4->M0AR = (uint32_t)tx_buffer;

    /* 读取一次DR，使其清空 */
    SPI2->DR;

    /* 等待发送区为空 */
    while (SPI_I2S_GetFlagStatus(SPI2, SPI_I2S_FLAG_TXE) == RESET)
        ;

    /* 打开DMA通道 */
    DMA_Cmd(DMA1_Stream3, ENABLE);
    DMA_Cmd(DMA1_Stream4, ENABLE);

    /* 传输完成 */
    while (DMA_GetFlagStatus(DMA1_Stream4, DMA_FLAG_TCIF4) == RESET)
        ;
    while (DMA_GetFlagStatus(DMA1_Stream3, DMA_FLAG_TCIF3) == RESET)
        ;

    /* 关闭DMA通道 */
    DMA_Cmd(DMA1_Stream3, DISABLE);
    DMA_Cmd(DMA1_Stream4, DISABLE);

    /* 清除DMA传输完成标志 */
    DMA_ClearFlag(DMA1_Stream3, DMA_FLAG_TCIF3);
    DMA_ClearFlag(DMA1_Stream4, DMA_FLAG_TCIF4);
}

#else  /* 使用一般的传输模式进行读写 */
static uint8_t SPI_ReadWriteByte(uint8_t data)
{
    uint16_t i = 0;
    /* 判断发送标志位 */
    while (SPI_I2S_GetFlagStatus(SPI2, SPI_I2S_FLAG_TXE) == RESET)
    {
        i++;
        if (i > 50000)
        {
            return 0;
        }
    }
    /* 发送数据 */
    SPI_I2S_SendData(SPI2, data);
    /* 判断接收标志位 */
    i = 0;
    while (SPI_I2S_GetFlagStatus(SPI2, SPI_I2S_FLAG_TXE) == RESET)
    {
        i++;
        if (i > 50000)
        {
            return 0;
        }
    }
    i = 0;
    while (SPI_I2S_GetFlagStatus(SPI2, SPI_I2S_FLAG_RXNE) == RESET)
    {
        i++;
        if (i > 50000)
        {
            return 0;
        }
    }
    /* 返回接收的数据 */
    return SPI_I2S_ReceiveData(SPI2);
}

void spi_trans(uint8_t *rxbuf,
               uint8_t *txbuf,
               uint16_t length)
{
    while (length--)
    {
        *rxbuf++ = SPI_ReadWriteByte(*txbuf++);
    }
}
#endif /* USE_DMA_TRANS */

unsigned long long SPI2_transfer64bit(unsigned long long data)
{
    unsigned long long ret;
    uint8_t *rx_buf = (uint8_t *)&ret;
    uint8_t *tx_buf = (uint8_t *)&data;
    GPIOB->BSRRH |= (1U << 12);
    spi_trans(rx_buf, tx_buf, sizeof(unsigned long long));
    GPIOB->BSRRL |= (1U << 12);
    return ret;
}

void NSS_enable(void)
{
    GPIOB->BSRRH |= (1U << 12);
}

void NSS_disable(void)
{
    GPIOB->BSRRL |= (1U << 12);
}

//其中Fsysclk为混频器VCO锁定内部时钟，Fc为载波中心频率，单位为MHz
u32 get_Carrier_frequency_control_word(const double Fc)
{
    u32 ret = 0;
    ret = (1ULL << 32) / Fsysclk * Fc;
    return ret;
}

//从控制字中获取载波频率值
double get_Carrierfreq_from_control_word(const u32 ftw)
{
    double ret = 0;
    ret = ftw * Fsysclk / (1ULL << 32);
    return ret;
}

//其中Fsysclk为混频器VCO锁定内部时钟,Fd为符号速率,单位为Mbps
u32 get_Symbol_rate_control_word(const double Fd)
{
    u32 ret = 0;
    double N = 4;
    if (Fd >= MHZ(6))
    {
        N = 4;
    }
    else if (Fd < MHZ(6) && Fd >= MHZ(3))
    {
        N = 8;
    }
    else if (Fd < MHZ(3) && Fd >= MHZ(1.5))
    {
        N = 16;
    }
    else if (Fd < MHZ(1.5) && Fd >= MHZ(0.75))
    {
        N = 32;
    }
    else if (Fd < MHZ(0.75) && Fd >= MHZ(0.375))
    {
        N = 64;
    }
    else if (Fd < MHZ(0.375) && Fd >= KHZ(187.5))
    {
        N = 128;
    }
    else if (Fd < KHZ(187.5) && Fd >= KHZ(93.75))
    {
        N = 256;
    }
    else if (Fd < KHZ(93.75) && Fd >= KHZ(46.875))
    {
        N = 512;
    }
    else if (Fd < KHZ(46.875) && Fd >= KHZ(24))
    {
        N = 1024;
    }
    else if (Fd < KHZ(24) && Fd >= KHZ(12))
    {
        N = 2048;
    }
    else if (Fd < KHZ(12) && Fd >= KHZ(4.8))
    {
        N = 4096;
    }
    else if (Fd < KHZ(4.8) && Fd >= KHZ(2.4))
    {
        N = 8192;
    }
    ret = (1ULL << 32) / Fsysclk * Fd * N * 2;
    return ret;
}

// void parse_receive_data(const unsigned long long data)
// {
//     u32 chnum = (data >> 40) & 0x07;               //通道号
//     u32 identification_code = (data >> 32) & 0x05; //识别码
//     u32 parameter_value = data & 0xFFFFFFF;        //参数值
// }

void device_init(void)
{
    OS_ERR err;
    printf("enter %s:%lu\r\n", __FUNCTION__, OSTimeGet(&err));
    pDevicepara = (Devicepara *)malloc(sizeof(Devicepara));
    if (pDevicepara == NULL)
    {
        perror("error...");
        return;
    }
    FLASH_ReadMoreData((uint16_t *)pDevicepara, sizeof(Devicepara) / 2);
    //pDevicepara->carrierfrequency = MHZ(100);
    pDevicepara->carrierfrequencycw = get_Carrier_frequency_control_word(pDevicepara->carrierfrequency);
    SPI2_transfer64bit(Demodulation_parameters | Carrier_frequency_control_word | pDevicepara->carrierfrequencycw);
    //pDevicepara->symbolrate = MHZ(1);
    pDevicepara->symbolratecw = get_Symbol_rate_control_word(pDevicepara->symbolrate);
    SPI2_transfer64bit(Demodulation_parameters | Symbol_rate_control_word | pDevicepara->symbolratecw);
    //pDevicepara->modulationsystem = 0;
    SPI2_transfer64bit(Demodulation_parameters | Modulation_system | pDevicepara->modulationsystem);
    //pDevicepara->spectruminversion = 0;
    SPI2_transfer64bit(Demodulation_parameters | Spectrum_inversion | pDevicepara->spectruminversion);
    //pDevicepara->symbolratevalue = MHZ(1);
    SPI2_transfer64bit(Demodulation_parameters | Symbol_rate_value | pDevicepara->symbolratevalue);
    //pDevicepara->balance = 0;
    SPI2_transfer64bit(Demodulation_parameters | Balance | pDevicepara->balance);
    //pDevicepara->decodingmode = 0;
    SPI2_transfer64bit(Decoding_parameters | Decoding_mode | pDevicepara->decodingmode);
    //pDevicepara->decodingrate = 0;
    SPI2_transfer64bit(Decoding_parameters | Decoding_rate | pDevicepara->decodingrate);
    //pDevicepara->RSdecodingmode = 0;
    SPI2_transfer64bit(Decoding_parameters | RS_Decoding_mode | pDevicepara->RSdecodingmode);
    //pDevicepara->RSmixeddepth = 0;
    SPI2_transfer64bit(Decoding_parameters | RS_Mixed_depth | pDevicepara->RSmixeddepth);
    //pDevicepara->differenceoptions = 0;
    SPI2_transfer64bit(Decoding_parameters | Difference_options | pDevicepara->differenceoptions);
    //pDevicepara->scramblerformat = 0;
    SPI2_transfer64bit(Decoding_parameters | Scrambler_format | pDevicepara->scramblerformat);
    //pDevicepara->scramblerinitialstate = 0;
    SPI2_transfer64bit(Decoding_parameters | Scrambler_initial_state | pDevicepara->scramblerinitialstate);
    //pDevicepara->framestructure = 0;
    SPI2_transfer64bit(Decoding_parameters | Frame_structure | pDevicepara->framestructure);
    //pDevicepara->acquisitionmode = 0;
    SPI2_transfer64bit(OUTPUT | Acquisition_mode | pDevicepara->acquisitionmode);
}

void device_free(void)
{
    if (pDevicepara != NULL)
    {
        free(pDevicepara);
        pDevicepara = NULL;
    }
}

void flash_write(void)
{
    FLASH_WriteMoreData((uint16_t *)pDevicepara, sizeof(Devicepara) / 2);
}
